﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;

namespace StyleMVVM.DependencyInjection
{
	public sealed class WeakSharedLifeCycleContainer : ILifeCycleContainer
	{
		private readonly object lockObject = new object();
		private volatile WeakReference sharedObject;

		public object RetrieveObject(IExportStrategy strategy,
		                             ExportLifeCycleMethod exportMethod,
		                             IDependencyInjectionContainer container,
		                             IInjectionContext injectionContext,
		                             [ReadOnlyArray] object[] constructorParams)
		{
			object returnValue = null;

			if (sharedObject != null)
			{
				returnValue = sharedObject.Target;
			}

			if (returnValue == null)
			{
				lock (lockObject)
				{
					if (sharedObject != null)
					{
						returnValue = sharedObject.Target;
					}

					if (returnValue == null)
					{
						IDisposalScope oldScope = injectionContext.DisposalScope;

						// null out disposal scope because weak object can't have children with disposable scopes
						injectionContext.DisposalScope = null;

						returnValue = exportMethod(injectionContext, constructorParams);

						injectionContext.DisposalScope = oldScope;

						if (returnValue != null)
						{
							sharedObject = new WeakReference(returnValue);
						}
					}
				}
			}

			return returnValue;
		}

		public void Shutdown()
		{
			sharedObject = null;
		}
	}
}